package com.gm.sfc.net;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.security.KeyStore;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.HttpResponse;
import org.apache.http.HttpVersion;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HTTP;
import org.apache.http.protocol.HttpContext;

import com.gm.sfc.util.LogUtil;

/**
 * データ通信クラス
 * @author $Author: t-hirano $
 * @version $Revision: 7049 $
 */
public class HttpRequestManager {
    private static final String TAG = "HttpRequestMnager";
    private static final int TIME_OUT = 5000;

    /**
     * POST処理<br>
     * @param act アクション
     * @return JSON
     * @throws SocketException タイムアウトの時に呼び出される
     */
    public String commonPost(String act, int id) throws SocketException {
        List<NameValuePair> objValuePairs = new ArrayList<NameValuePair>(2);
        objValuePairs.add(new BasicNameValuePair("パラメータ", act));
        objValuePairs.add(new BasicNameValuePair("user_id", String.valueOf(id)));
        return HttpRequestManager.sendPostData(objValuePairs, "http://example.com");
    }

    public static String sendPostData(List<NameValuePair> objValuePairs, String url) throws SocketException {
        return sendPostData(objValuePairs, null, url);

    }

    public static String sendGetData(String url) throws SocketException {
        return sendGetData(null, url);

    }

    /**
     * ポストデータを送信し、 結果を取得する。
     * @param objValuePairs パラメータ
     * @param url URL
     * @return レスポンスデータ
     * @throws SocketException
     */
    private static String sendPostData(List<NameValuePair> objValuePairs, List<NameValuePair> objHeaderPairs, String url) throws SocketException {
        String xml = null;
        try {
            HttpClient objHttp = new DefaultHttpClient();
            HttpContext httpcontext = new BasicHttpContext();
            KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
            trustStore.load(null, null);
            SSLSocketFactory sf = new MySslSocketFactory(trustStore);
            sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
            Scheme https = new Scheme("https", sf, 443);
            objHttp.getConnectionManager().getSchemeRegistry().register(https);
            httpcontext.setAttribute(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
            httpcontext.setAttribute(CoreProtocolPNames.USE_EXPECT_CONTINUE, false);
            httpcontext.setAttribute(CoreProtocolPNames.HTTP_CONTENT_CHARSET, HTTP.UTF_8);

            objHttp.getParams().setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, TIME_OUT); // 接続のタイムアウト
            objHttp.getParams().setIntParameter(CoreConnectionPNames.SO_TIMEOUT, TIME_OUT);// データ取得タイムアウト
            HttpProtocolParams.setContentCharset(objHttp.getParams(), HTTP.UTF_8);
            HttpPost objPost = new HttpPost(url);
            if (objHeaderPairs != null) {
                for (NameValuePair nvp : objHeaderPairs) {
                    objPost.setHeader(nvp.getName(), nvp.getValue());
                }
            }

            objPost.setEntity(new UrlEncodedFormEntity(objValuePairs, "UTF-8"));
            HttpResponse objResponse = objHttp.execute(objPost, httpcontext);

            if (objResponse.getStatusLine().getStatusCode() < 400) {
                InputStream objStream = objResponse.getEntity().getContent();
                InputStreamReader objReader = new InputStreamReader(objStream);
                BufferedReader objBuf = new BufferedReader(objReader);
                StringBuilder objJson = new StringBuilder();
                String sLine;
                while ((sLine = objBuf.readLine()) != null) {
                    objJson.append(sLine);
                }
                xml = objJson.toString();
                objStream.close();
            }
        } catch (SocketTimeoutException e) {
            LogUtil.logStack(TAG, e);
            throw new SocketException();
        } catch (SocketException e) {
            LogUtil.logStack(TAG, e);
            throw new SocketException();
        } catch (IOException e) {
            LogUtil.logStack(TAG, e);
        } catch (Exception e) {
            LogUtil.logStack(TAG, e);
        }
        if (xml == null)
            throw new SocketException();
        return xml;
    }

    /**
     * FilePOST処理<br>
     * @param url
     * @return
     */
    public static String sendPostData(String url, List<NameValuePair> objValuePairs, File attFile) throws SocketException {
        if (attFile != null) {
            LogUtil.logD(TAG, "" + attFile.exists());
        }
        String xml = null;
        try {
            HttpClient objHttp = new DefaultHttpClient();
            HttpContext httpcontext = new BasicHttpContext();
            KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
            trustStore.load(null, null);
            SSLSocketFactory sf = new MySslSocketFactory(trustStore);
            sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
            Scheme https = new Scheme("https", sf, 443);
            objHttp.getConnectionManager().getSchemeRegistry().register(https);
            httpcontext.setAttribute(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
            httpcontext.setAttribute(CoreProtocolPNames.USE_EXPECT_CONTINUE, false);
            httpcontext.setAttribute(CoreProtocolPNames.HTTP_CONTENT_CHARSET, HTTP.UTF_8);

            objHttp.getParams().setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, TIME_OUT); // 接続のタイムアウト
            objHttp.getParams().setIntParameter(CoreConnectionPNames.SO_TIMEOUT, TIME_OUT);// データ取得タイムアウト
            HttpProtocolParams.setContentCharset(objHttp.getParams(), HTTP.UTF_8);
            // HttpPost objPost = new HttpPost(url);

            HttpPost method = new HttpPost(url);
            MultipartEntity entity = new MultipartEntity();

            // テキストデータ
            for (NameValuePair pair : objValuePairs) {
                // String destr = URLDecoder.decode(pair.getValue());
                // entity.addPart(pair.getName(), new StringBody(destr, Charset.forName("UTF-8")));
                // entity.addPart(pair.getName(), new StringBody(pair.getValue(), Charset.forName("UTF-8")));
                entity.addPart(pair.getName(), new StringBody(pair.getValue()));
            }
            // 添付ファイル
            if (attFile != null) {
                // entity.addPart("photo_data", new FileBody(attFile, "application/octet-stream"));
                entity.addPart("img_file", new FileBody(attFile));
            }

            method.setEntity(entity);
            method.setHeader("Connection", "Keep-Alive");

            HttpResponse objResponse = objHttp.execute(method);
            if (objResponse.getStatusLine().getStatusCode() < 400) {
                InputStream objStream = objResponse.getEntity().getContent();
                InputStreamReader objReader = new InputStreamReader(objStream);
                BufferedReader objBuf = new BufferedReader(objReader);
                StringBuilder objJson = new StringBuilder();
                String sLine;
                while ((sLine = objBuf.readLine()) != null) {
                    objJson.append(sLine);
                }
                xml = objJson.toString();
                objStream.close();
            }
        } catch (SocketTimeoutException e) {
            LogUtil.logStack(TAG, e);
            throw new SocketException();
        } catch (SocketException e) {
            LogUtil.logStack(TAG, e);
            throw new SocketException();
        } catch (Exception e) {
            LogUtil.logStack(TAG, e);
        }
        if (xml == null)
            throw new SocketException();
        return xml;
    }

    /**
     * データを送信し、XMLを取得する
     * @param url URL
     * @return レスポンスデータ
     * @throws SocketException
     */
    public static String sendGetData(List<NameValuePair> objHeaderPairs, String url) throws SocketException {
        String xml = null;
        try {
            HttpParams httpParms = new BasicHttpParams();
            httpParms.setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, TIME_OUT); // 接続のタイムアウト
            httpParms.setIntParameter(CoreConnectionPNames.SO_TIMEOUT, TIME_OUT);// データ取得タイムアウト
            HttpClient objHttp = new DefaultHttpClient(httpParms);
            HttpGet objGet = new HttpGet(url);
            if (objHeaderPairs != null) {
                for (NameValuePair nvp : objHeaderPairs) {
                    objGet.setHeader(nvp.getName(), nvp.getValue());
                }
            }

            HttpResponse objResponse = objHttp.execute(objGet);
            if (objResponse.getStatusLine().getStatusCode() < 400) {
                InputStream objStream = objResponse.getEntity().getContent();
                InputStreamReader objReader = new InputStreamReader(objStream);
                BufferedReader objBuf = new BufferedReader(objReader);
                StringBuilder objJson = new StringBuilder();
                String sLine;
                while ((sLine = objBuf.readLine()) != null) {
                    objJson.append(sLine);
                }
                xml = objJson.toString();
                objStream.close();
            }
        } catch (SocketTimeoutException e) {
            LogUtil.logStack(TAG, e);
            throw new SocketException();
        } catch (SocketException e) {
            LogUtil.logStack(TAG, e);
            throw new SocketException();
        } catch (IOException e) {
            LogUtil.logStack(TAG, e);
        }
        if (xml == null)
            throw new SocketException();
        return xml;
    }

    /**
     * @param serverPath
     * @param apiPath
     * @param objValuePairs
     * @return
     */
    public static String makeGetUrl(String serverPath, String apiPath, List<NameValuePair> objValuePairs) {
        StringBuilder url = new StringBuilder(serverPath);
        url.append(apiPath);
        boolean first = true;
        for (NameValuePair param : objValuePairs) {
            if (first) {
                url.append("?");
            } else {
                url.append("&");
            }
            url.append(param.getName()).append("=").append(param.getValue());
            first = false;
        }
        return url.toString();
    }
}
